/**
 * @FilePath: \ros2\src\tools\shared_parameters\src\include\shared_parameters\shared_params_interface.hpp
 * @Description:  
 * @Author: haibo
 * @Version: 1.0.0
 * @LastEditors: haibo ashengzi@163.com
 * @LastEditTime: 2025-02-20 20:40:49
 * @Copyright (c) 2025 by 临工智能信息科技有限公司, All Rights Reserved. 
**/
#pragma once
#include "shared_parameters/shared_memory_manager.hpp"
#include <any>
#include <string>
#include <typeinfo>
#include <stdexcept>
#include <sstream>
#include <map>
#include <vector>
#include <unordered_map>

class SharedParamsInterface {
public:
    // ParamValue 结构体定义
    struct ParamValue {
        enum class Type { INT, DOUBLE, STRING, BOOL } type;
        std::any value;

        // 构造函数
        ParamValue() : type(Type::INT), value(0) {}
        ParamValue(int v) : type(Type::INT), value(v) {}
        ParamValue(double v) : type(Type::DOUBLE), value(v) {}
        ParamValue(const std::string& v) : type(Type::STRING), value(v) {}
        ParamValue(bool v) : type(Type::BOOL), value(v) {}

        // 复制构造函数
        ParamValue(const ParamValue& other) = default;
        // 移动构造函数
        ParamValue(ParamValue&& other) noexcept = default;
        // 赋值运算符
        ParamValue& operator=(const ParamValue& other) = default;
        // 移动赋值运算符
        ParamValue& operator=(ParamValue&& other) noexcept = default;

        template<typename T>
        T getValue() const {
            try {
                return std::any_cast<T>(value);
            } catch (const std::bad_any_cast& e) {
                DEBUG("Type mismatch in getValue()");
            }
        }
        
        template<typename T>
        const T& getValueRef() const {
            try {
                return std::any_cast<const T&>(value);
            } catch (const std::bad_any_cast& e) {
                DEBUG("Type mismatch in getValueRef()");
            }
        }

        std::string toString() const {
            try {
                std::stringstream ss;
                switch (type) {
                    case Type::INT:
                        ss << std::any_cast<int>(value);
                        break;
                    case Type::DOUBLE:
                        ss << std::any_cast<double>(value);
                        break;
                    case Type::STRING:
                        ss << std::any_cast<std::string>(value);
                        break;
                    case Type::BOOL:
                        ss << (std::any_cast<bool>(value) ? "true" : "false");
                        break;
                }
                return ss.str();
            } catch (const std::exception& e) {
                return "ERROR: " + std::string(e.what());
            }
        }
    };

    using ParamMap = std::unordered_map<std::string, ParamValue>;

    // 初始化函数
    static bool initialize() {
        auto& manager = SharedMemoryManager::getInstance();
        if (!manager.initializeSharedMemory()) {
            return manager.connectToSharedMemory();
        }
        return true;
    }

private:
    // 辅助函数：构建参数完整名称
    static std::string buildParamKey(const std::string& node_name, const std::string& param_name) {
        return node_name + "/" + param_name;
    }

    // 辅助函数：创建共享字符串
    static SharedData::SharedString createSharedString(
        const std::string& str, 
        bip::managed_shared_memory* shm) {
        if (!shm || !shm->get_segment_manager()) {
            throw std::runtime_error("Invalid shared memory segment");
        }
        auto alloc = shm->get_segment_manager();
        return SharedData::SharedString(str.c_str(), alloc);
    }

    // 辅助函数：转换参数类型
    static SharedData::Parameter::Type convertParamType(ParamValue::Type type) {
        switch (type) {
            case ParamValue::Type::INT:
                return SharedData::Parameter::Type::INT;
            case ParamValue::Type::DOUBLE:
                return SharedData::Parameter::Type::DOUBLE;
            case ParamValue::Type::STRING:
                return SharedData::Parameter::Type::STRING;
            case ParamValue::Type::BOOL:
                return SharedData::Parameter::Type::BOOL;
            default:
                DEBUG("Unknown parameter type");
                throw std::invalid_argument("Invalid parameter type: " + std::to_string(static_cast<int>(type)));
        }
    }

    // 辅助函数：设置参数内部实现
    static bool setParamInternal(const std::string& node_name,
                                const std::string& param_name,
                                const std::any& value,
                                SharedData::Parameter::Type type,
                                bip::managed_shared_memory* shm,
                                SharedData::ParamMap* params) {
        auto param_key = createSharedString(buildParamKey(node_name, param_name), shm);
        auto alloc = shm->get_segment_manager();
        SharedData::Parameter new_param(alloc);
        new_param.type = type;

        try {
            switch (type) {
                case SharedData::Parameter::Type::INT:
                    new_param.value.i = std::any_cast<int>(value);
                    break;
                case SharedData::Parameter::Type::DOUBLE:
                    new_param.value.d = std::any_cast<double>(value);
                    break;
                case SharedData::Parameter::Type::BOOL:
                    new_param.value.b = std::any_cast<bool>(value);
                    break;
                case SharedData::Parameter::Type::STRING:
                    new_param.str_value = createSharedString(std::any_cast<std::string>(value), shm);
                    break;
            }
            params->insert_or_assign(param_key, std::move(new_param));
        } catch (const std::exception& e) {
            DEBUG("Error setting parameter value: %s", e.what());
            return false;
        }
        return true;
    }

public:
    // 设置单个参数
    static bool setParam(const std::string& node_name, 
                        const std::string& param_name, 
                        const std::any& value) {
        auto& manager = SharedMemoryManager::getInstance();
        auto* shm = manager.getSharedMemory();
        auto* mutex = manager.getMutex();
        auto* shared_params = manager.getParamsMap();

        if (!shm || !mutex || !shared_params) {
            DEBUG("Error: Shared memory not initialized");
            return false;
        }

        SharedData::Parameter::Type type;
        if (value.type() == typeid(int)) {
            type = SharedData::Parameter::Type::INT;
        } else if (value.type() == typeid(double)) {
            type = SharedData::Parameter::Type::DOUBLE;
        } else if (value.type() == typeid(bool)) {
            type = SharedData::Parameter::Type::BOOL;
        } else if (value.type() == typeid(std::string)) {
            type = SharedData::Parameter::Type::STRING;
        } else {
            throw std::runtime_error("Unsupported parameter type");
        }

        bip::scoped_lock<bip::named_mutex> lock(*mutex);
        return setParamInternal(node_name, param_name, value, type, shm, shared_params);
    }

    // 批量设置参数
    static bool setNodeParams(const std::string& node_name, const ParamMap& params) {
        auto& manager = SharedMemoryManager::getInstance();
        auto* shm = manager.getSharedMemory();
        auto* mutex = manager.getMutex();
        auto* shared_params = manager.getParamsMap();

        if (!shm || !mutex || !shared_params) {
            DEBUG("Error: Shared memory not initialized");
            return false;
        }

        try {
            bip::scoped_lock<bip::named_mutex> lock(*mutex);
            
            for (const auto& param_pair : params) {
                const std::string& param_name = param_pair.first;
                const ParamValue& param_value = param_pair.second;
                
                auto shared_type = convertParamType(param_value.type);
                setParamInternal(node_name, param_name, param_value.value, 
                               shared_type, shm, shared_params);
            }
            
        } catch (const std::exception& e) {
            DEBUG("Error setting node parameters: %s", e.what());
            return false;
        }
        return true;
    }

    // 获取单个参数
    template<typename T>
    static T getParam(const std::string& node_name, const std::string& param_name, const T& default_value) {
        // DEBUG("shared_params getParam %s/%s", node_name.c_str(), param_name.c_str());
        auto& manager = SharedMemoryManager::getInstance();
        auto* shm = manager.getSharedMemory();
        auto* mutex = manager.getMutex();
        auto* params = manager.getParamsMap();
        
        if (!shm || !mutex || !params) {
            DEBUG("Error: Shared memory not initialized");
            return default_value;
        }

        bip::scoped_lock<bip::named_mutex> lock(*mutex);
   
        auto param_key = createSharedString(buildParamKey(node_name, param_name), shm);
        auto it = params->find(param_key);
        
        if (it == params->end()) {
            DEBUG("Error: Parameter not found: %s/%s return default value", node_name.c_str(), param_name.c_str());
            return default_value;
        }

        const auto& param = it->second;

        if constexpr (std::is_same_v<T, int>) {
            if (param.type != SharedData::Parameter::Type::INT) {
                DEBUG("Type mismatch: expected INT");
                return default_value;
            }
            return static_cast<T>(param.value.i);
        }
        else if constexpr (std::is_same_v<T, double>) {
            if (param.type != SharedData::Parameter::Type::DOUBLE) {
                DEBUG("Type mismatch: expected DOUBLE");
                return default_value;
            }
            return param.value.d;
        }
        else if constexpr (std::is_same_v<T, bool>) {
            if (param.type != SharedData::Parameter::Type::BOOL) {
                DEBUG("Type mismatch: expected BOOL");
                return default_value;
            }
            return param.value.b;
        }
        else if constexpr (std::is_same_v<T, std::string>) {
            if (param.type != SharedData::Parameter::Type::STRING) {
                DEBUG("Type mismatch: expected STRING");
                return default_value;
            }

            if (!param.str_value.empty()) {
                return std::string(param.str_value.c_str());
            }  else {
                DEBUG("String: empty value, return default value!");
                return default_value; 
            }
        }
        else {
            DEBUG("Unsupported parameter type");
            return default_value;
        }
    }

    // 获取节点所有参数
    static ParamMap getNodeParams(const std::string& node_name) {
        // DEBUG("shared_params getNodeParams %s", node_name.c_str());
        auto& manager = SharedMemoryManager::getInstance();
        auto* shm = manager.getSharedMemory();
        auto* mutex = manager.getMutex();
        auto* shared_params = manager.getParamsMap();

        if (!shm || !mutex || !shared_params) {
            DEBUG("Error: Shared memory not initialized");
            return ParamMap();
        }

        ParamMap result;
        std::string node_prefix = node_name + "/";

        bip::scoped_lock<bip::named_mutex> lock(*mutex);

        for (const auto& pair : *shared_params) {
            std::string key = pair.first.c_str();
            if (key.substr(0, node_prefix.length()) == node_prefix) {
                std::string param_name = key.substr(node_prefix.length());
                const auto& param = pair.second;

                switch (param.type) {
                    case SharedData::Parameter::Type::INT:
                        result.emplace(param_name, ParamValue(static_cast<int>(param.value.i)));
                        break;
                    case SharedData::Parameter::Type::DOUBLE:
                        result.emplace(param_name, ParamValue(param.value.d));
                        break;
                    case SharedData::Parameter::Type::STRING:
                        result.emplace(param_name, ParamValue(std::string(param.str_value.c_str())));
                        break;
                    case SharedData::Parameter::Type::BOOL:
                        result.emplace(param_name, ParamValue(param.value.b));
                        break;
                }
            }
        }

        return result;
    }

    // 列出所有参数
    struct NodeParamInfo {
        std::string node_name;
        std::string param_name;
        std::string param_type;
        std::string param_value;
    };

    static std::vector<NodeParamInfo> listAllParams() {
        auto& manager = SharedMemoryManager::getInstance();
        auto* shm = manager.getSharedMemory();
        auto* mutex = manager.getMutex();
        auto* shared_params = manager.getParamsMap();

        if (!shm || !mutex || !shared_params) {
            DEBUG("Error: Shared memory not initialized");
            return std::vector<NodeParamInfo>();
        }

        std::vector<NodeParamInfo> result;
        bip::scoped_lock<bip::named_mutex> lock(*mutex);

        for (const auto& pair : *shared_params) {
            std::string full_key = pair.first.c_str();
            const auto& param = pair.second;

            size_t separator_pos = full_key.find('/');
            if (separator_pos != std::string::npos) {
                NodeParamInfo info;
                info.node_name = full_key.substr(0, separator_pos);
                info.param_name = full_key.substr(separator_pos + 1);

                switch (param.type) {
                    case SharedData::Parameter::Type::INT:
                        info.param_type = "INT";
                        info.param_value = std::to_string(param.value.i);
                        break;
                    case SharedData::Parameter::Type::DOUBLE:
                        info.param_type = "DOUBLE";
                        info.param_value = std::to_string(param.value.d);
                        break;
                    case SharedData::Parameter::Type::STRING:
                        info.param_type = "STRING";
                        info.param_value = param.str_value.c_str();
                        break;
                    case SharedData::Parameter::Type::BOOL:
                        info.param_type = "BOOL";
                        info.param_value = param.value.b ? "true" : "false";
                        break;
                }

                result.push_back(info);
            }
        }

        return result;
    }
};